package com.axis2.common.util;

import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author yemulin
 * @create 2012-8-20 上午10:43:51
 */
public class HttpUtil {

	private static Logger log = LoggerFactory.getLogger(HttpUtil.class);

	/**
	 * 发送请求
	 * 
	 * @param url
	 * @param postData
	 * @return
	 */
	public static String postSubmit(String url, String postData) {

		log.debug("url:{},postData:{}", url, postData);

		String data = "";
		try {
			URL dataUrl = new URL(url);

			HttpURLConnection con = (HttpURLConnection) dataUrl.openConnection();

			con.setRequestMethod("POST");

			System.setProperty("sun.net.client.defaultConnectTimeout", String.valueOf("5000000"));
			System.setProperty("sun.net.client.defaultReadTimeout", String.valueOf("5000000"));

			con.setRequestProperty("User-Agent", "Mozilla/MSIE");
			con.setDoOutput(true);
			con.setDoInput(true);

			PrintWriter out = new PrintWriter(new OutputStreamWriter(con.getOutputStream(), "GBK"));
			out.print(postData);
			out.close();

			BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(), "GBK"));
			String line = "";
			while ((line = in.readLine()) != null) {
				data = data + "\n" + line;
			}

			con.disconnect();
		} catch (Exception ex) {
			log.error("Exception :{}", ex);
		}
		return data;
	}

	/**
	 * 
	 * @param url
	 * @param postData
	 * @param encodetype
	 * @return
	 */
	public static String postSubmit(String url, String postData, String encodetype) {

		log.info("url:{},postData:{}", url, postData);
		
		String data = "";
		try {
			URL dataUrl = new URL(url);
			
			HttpURLConnection con = (HttpURLConnection) dataUrl.openConnection();
			
			con.setRequestMethod("POST");

			System.setProperty("sun.net.client.defaultConnectTimeout", String.valueOf("5000000"));
			System.setProperty("sun.net.client.defaultReadTimeout", String.valueOf("5000000"));
			
			con.setRequestProperty("User-Agent", "Mozilla/MSIE");
			con.setDoOutput(true);
			con.setDoInput(true);

			PrintWriter out = new PrintWriter(new OutputStreamWriter(con.getOutputStream(), encodetype));
			out.print(postData);
			out.close();

			BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(), encodetype));
			String line = "";
			while ((line = in.readLine()) != null) {
				data = data + "\n" + line;
			}
			con.disconnect();
		} catch (Exception ex) {
			log.error("postSubmit Exception:{}", ex.getMessage(),ex);
		}
		return data;
	}

	/**
	 * post请求设置响应超时时间
	 * @param url
	 * @param postData
	 * @param encodetype
	 * @return
	 */
	public static Map<String,String> postSubmitData(String url, String postData, String timeOut){
		log.debug("postSubmitData:{}", url, postData);
		try {
			HostnameVerifier ve = new HostnameVerifier() {

				public boolean verify (String urlHostName, SSLSession session) {
					log.info("Warning: URL Host: {} vs. {}", urlHostName, session.getPeerHost());
					return true;
				}
			};
			TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {

				public X509Certificate[] getAcceptedIssuers () {
					return null;
				}

				public void checkClientTrusted (X509Certificate[] certs, String authType) {
				}

				public void checkServerTrusted (X509Certificate[] certs, String authType) {
				}
			} };
			SSLContext sc = SSLContext.getInstance("TLS");
			sc.init(null, trustAllCerts, null);
			HttpsURLConnection.setDefaultHostnameVerifier(ve);
			HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
		} catch (Exception e) {
			log.info("忽略https证书失败", e);
		}
		
		Map<String,String> dataMap = new HashMap<String,String>();
		String data = "";
		/*请求发送数据开始时间*/
		long startTime = System.currentTimeMillis();
		dataMap.put("startTime", String.valueOf(startTime));
		try {
			//URL dataUrl = new URL(url);
			//HttpURLConnection con = (HttpURLConnection) dataUrl.openConnection();
			HttpsURLConnection con = (HttpsURLConnection) new URL(null, url,
			        new sun.net.www.protocol.https.Handler()).openConnection();
			con.setRequestMethod("POST");
			con.setConnectTimeout(Integer.parseInt(timeOut));
			con.setReadTimeout(Integer.parseInt(timeOut));
			con.setRequestProperty("User-Agent", "Mozilla/MSIE");
			con.setDoOutput(true);
			con.setDoInput(true);
			PrintWriter out = new PrintWriter(new OutputStreamWriter(con.getOutputStream(), "UTF-8"));
			out.print(postData);
			out.close();
			BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
			String line = "";
			while ((line = in.readLine()) != null) {
				data = data + "\n" + line;
			}
			con.disconnect();
			dataMap.put("data", data);
		} catch (ConnectTimeoutException ce) { 
			log.error("ConnectTimeoutException :{}", ce.getMessage(), ce);
			dataMap.put("failure", "connectTimeout");
            System.out.println("连接超时....");
		} catch (SocketTimeoutException se){
			log.error("SocketTimeoutException :{}", se.getMessage(), se);
			dataMap.put("failure", "socketTimeout");
			System.out.println("请求超时....");
		} catch (Exception ex) {
			log.error("Exception :{}", ex.getMessage(), ex);
			dataMap.put("failure", "exception");
		}
		return dataMap;
	}

	
	/**
	 * 发送查询数据
	 * 
	 * @param url
	 * @param postData
	 * @param xmlKey
	 * @param xmlValue
	 * @return
	 */
	public static String postData(String url, String postData, String xmlKey, String xmlValue) {
		log.debug("url:{},postData:{}", url, postData);

		String data = "";

		try {
			URL dataUrl = new URL(url);

			HttpURLConnection con = (HttpURLConnection) dataUrl.openConnection();

			con.setRequestMethod("POST");

			System.setProperty("sun.net.client.defaultConnectTimeout", String.valueOf("5000000"));
			System.setProperty("sun.net.client.defaultReadTimeout", String.valueOf("5000000"));

			con.setRequestProperty(xmlKey, xmlValue);
			con.setDoOutput(true);
			con.setDoInput(true);

			PrintWriter out = new PrintWriter(new OutputStreamWriter(con.getOutputStream(), "GBK"));
			out.print(postData);
			out.close();

			BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(), "GBK"));
			String line = "";
			while ((line = in.readLine()) != null) {
				data = data + "\n" + line;
			}
			con.disconnect();
		} catch (Exception ex) {
			log.error("Exception :{}", ex);
		}
		return data;
	}

	// https需要证书发送
	// HttpsURLConnection 用javax.net.ssl.HttpsURLConnection
	public static String httpssl(String url, String privatekey, String pwd, String postData, String encodetype) {
		String result = "";
		BufferedReader in = null;
		try {

			// 设置私钥
			KeyStore ks = KeyStore.getInstance("pkcs12");
			ks.load(new FileInputStream(privatekey), pwd.toCharArray());
			KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
			kmf.init(ks, pwd.toCharArray());

			// 信任服务器证书
			TrustManager tm = new miTM();
			TrustManager[] trustAllCerts = new TrustManager[1];
			trustAllCerts[0] = tm;

			// 设置ssl
			SSLContext sc = SSLContext.getInstance("SSL");
			sc.init(kmf.getKeyManagers(), trustAllCerts, null);
			SSLSocketFactory ssf = sc.getSocketFactory();

			URL myURL = new URL(url);

			HttpsURLConnection httpsConn = (HttpsURLConnection) myURL.openConnection();
			httpsConn.setSSLSocketFactory(ssf);
			httpsConn.setRequestMethod("POST");

			System.setProperty("sun.net.client.defaultConnectTimeout", String.valueOf("5000000"));
			System.setProperty("sun.net.client.defaultReadTimeout", String.valueOf("5000000"));

			httpsConn.setRequestProperty("User-Agent", "Mozilla/MSIE");
			httpsConn.setDoOutput(true);
			httpsConn.setDoInput(true);

			PrintWriter out = new PrintWriter(new OutputStreamWriter(httpsConn.getOutputStream(), encodetype));
			out.print(postData);
			out.close();

			in = new BufferedReader(new InputStreamReader(httpsConn.getInputStream(), encodetype));
			String line = "";
			while ((line = in.readLine()) != null) {
				result = result + "\n" + line;
			}
			httpsConn.disconnect();
		} catch (Exception ex) {
			log.error("Exception :{}", ex);
			result = "0";
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}
	
	// https需要证书发送
	// HttpsURLConnection 用com.sun.net.ssl.HttpsURLConnection
	public static String httpsslOld(String url, String privatekey, String pwd, String postData, String encodetype) {
		String result = "";
		BufferedReader in = null;
		try {
			
			// 设置私钥
			KeyStore ks = KeyStore.getInstance("pkcs12");
			ks.load(new FileInputStream(privatekey), pwd.toCharArray());
			KeyManagerFactory kmf = KeyManagerFactory.getInstance("sunx509");
			kmf.init(ks, pwd.toCharArray());

			// 信任服务器证书
			TrustManager tm = new miTM();
			TrustManager[] trustAllCerts = new TrustManager[1];
			trustAllCerts[0] = tm;

			// 设置ssl
			SSLContext sc = SSLContext.getInstance("SSL");
			sc.init(kmf.getKeyManagers(), trustAllCerts, null);
			SSLSocketFactory ssf = sc.getSocketFactory();

			//URL myURL = new URL(url);
			 //指定流处理器实现的handler，用其他构造会用较旧的实现
			URL myURL= new URL(null, url, new sun.net.www.protocol.https.Handler()); 

			HttpsURLConnection httpsConn = (HttpsURLConnection) myURL.openConnection();
			httpsConn.setSSLSocketFactory(ssf);
			httpsConn.setRequestMethod("POST");

			System.setProperty("sun.net.client.defaultConnectTimeout", String.valueOf("5000000"));
			System.setProperty("sun.net.client.defaultReadTimeout", String.valueOf("5000000"));

			httpsConn.setRequestProperty("User-Agent", "Mozilla/MSIE");
			httpsConn.setDoOutput(true);
			httpsConn.setDoInput(true);

			PrintWriter out = new PrintWriter(new OutputStreamWriter(httpsConn.getOutputStream(), encodetype));
			out.print(postData);
			out.close();

			in = new BufferedReader(new InputStreamReader(httpsConn.getInputStream(), encodetype));
			String line = "";
			while ((line = in.readLine()) != null) {
				result = result + "\n" + line;
			}
			httpsConn.disconnect();
		} catch (Exception ex) {
			log.error("Exception :{}",ex);
			result = "0";
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 获取提交信息
	 * 
	 * @param url
	 * @param param
	 * @return
	 */
	public static String getSubmit(String url, String param) {
		String result = "";
		BufferedReader in = null;
		try {
			String urlName = url + "?" + param;
			URL realUrl = new URL(urlName);

			URLConnection conn = realUrl.openConnection();

			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");

			conn.connect();

			in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line = "";
			while ((line = in.readLine()) != null) {
				result = result + "\n" + line;
			}
		} catch (Exception e) {
			log.error("发送GET请求出现异常:{}", e);
			e.printStackTrace();
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 获取提交信息
	 * 
	 * @param url
	 * @param param
	 * @param encode
	 * @return
	 */
	public static String getSubmit(String url, String param, String encode) {
		String result = "";
		BufferedReader in = null;
		try {
			String urlName = url + "?" + param;
			URL realUrl = new URL(urlName);

			URLConnection conn = realUrl.openConnection();

			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");

			conn.connect();

			in = new BufferedReader(new InputStreamReader(conn.getInputStream(), encode));
			String line = "";
			while ((line = in.readLine()) != null) {
				result = result + "\n" + line;
			}
		} catch (Exception e) {
			log.error("发送GET请求出现异常:{}", e);
			e.printStackTrace();
		} finally {
			try {
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return result;
	}

	// HttpsURLConnection 用javax.net.ssl.HttpsURLConnection
	public static void trustAllHttpsCertificates() throws Exception {
		TrustManager[] trustAllCerts = new TrustManager[1];

		TrustManager tm = new miTM();

		trustAllCerts[0] = tm;

		SSLContext sc = SSLContext.getInstance("SSL");

		sc.init(null, trustAllCerts, null);
		HostnameVerifier ve = new HostnameVerifier() {
			public boolean verify(String urlHostName, SSLSession session) {
				log.info("Warning: URL Host: {} vs. {}", urlHostName, session.getPeerHost());
				return true;
			}
		};
		HttpsURLConnection.setDefaultHostnameVerifier(ve);
		HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
	}

	// HttpsURLConnection 用com.sun.net.ssl.HttpsURLConnection
	public static void trustAllHttpsCertificatesOld() throws Exception {
		TrustManager[] trustAllCerts = new TrustManager[1];

		TrustManager tm = new miTM();

		trustAllCerts[0] = tm;

		SSLContext sc = SSLContext.getInstance("SSL");

		sc.init(null, trustAllCerts, null);
		com.sun.net.ssl.HostnameVerifier ve = new com.sun.net.ssl.HostnameVerifier() {
			public boolean verify(String urlHostName, String s1) {
				log.info("Warning: URL Host: {} vs. {}", urlHostName, s1);
				return true;
			}
		};
		com.sun.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(ve);
		com.sun.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
	}

	/**
	 * @param url
	 * @param password
	 */
	public static void SSLConnect(String url, String password) {
		try {
			trustAllHttpsCertificates();
			SSLSocketFactory Factory = null;
			SSLContext ctx = SSLContext.getInstance("TLS");

			KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
			TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");

			KeyStore ks = KeyStore.getInstance("JKS");

			File file = new File(url);

			if (!file.isFile()) {
				throw new IOException("Missing keystore = " + url);
			}

			ks.load(new FileInputStream(file), password.toCharArray());

			kmf.init(ks, password.toCharArray());

			tmf.init(ks);
			ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
			Factory = ctx.getSocketFactory();

			SSLSocket socket = (SSLSocket) Factory.createSocket("https://corporbank.icbc.com.cn", 443);

			trustAllHttpsCertificates();
			SSLSession session = socket.getSession();
			if (session == null) {
				log.error("(ClientAuthA) Failed to get session context");
			}
		} catch (Exception e) {
			log.error("SSL连接异常：" + e.toString());
		}
	}

	/**
	 * @Description: http post提交
	 * @param url
	 *            提交的url
	 * @param paramMap
	 *            参数map
	 * @param charSet
	 *            字符集
	 * @return String 返回数据
	 * @throws HttpException
	 *             IOException
	 */
	public static String post(String url, Map<String, String> paramMap, String charSet) throws HttpException,
			IOException {
		HttpClient client = new HttpClient();
		System.setProperty("sun.net.client.defaultConnectTimeout", String.valueOf("5000000"));
		// post方法
		PostMethod method = new PostMethod(url);
		// 设置参数编码
		method.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, charSet);
		method.getParams().setParameter(HttpMethodParams.USER_AGENT,
				"Mozilla/5.0 (X11; U; Linux i686; zh-CN; rv:1.9.1.2) Gecko/20090803 Fedora/3.5.2-2.fc11 Firefox/3.5.2");//
		// 参数设置
		Iterator<Entry<String, String>> iter = paramMap.entrySet().iterator();
		while (iter.hasNext()) {
			Entry<String, String> entry = iter.next();
			method.addParameter(new NameValuePair(entry.getKey(), entry.getValue()));
		}
		// 发起调用
		System.out.println("超时时间  " + client.getParams().getConnectionManagerTimeout());;
		System.out.println("超时时间  " + client.getHttpConnectionManager().getParams().getConnectionTimeout());;
		
		client.executeMethod(method);
		String response = "";
		if (method.getStatusCode() == HttpStatus.SC_OK) {
			response = method.getResponseBodyAsString();
		}
		return response;
	}

	/**
	 * @param str
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String urlEncode(String str) throws UnsupportedEncodingException {
		return urlEncode(str, "UTF-8");
	}

	/**
	 * @param str
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String urlDecode(String str) throws UnsupportedEncodingException {
		return urlDecode(str, "UTF-8");
	}

	/**
	 * @param str
	 * @param charset
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String urlDecode(String str, String charset) throws UnsupportedEncodingException {
		return URLDecoder.decode(str, charset);
	}

	/**
	 * @param str
	 * @param charset
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String urlEncode(String str, String charset) throws UnsupportedEncodingException {
		return URLEncoder.encode(str, charset);
	}

	public static String postWs(String url, String data) throws Exception {
		return postWs(url, data, "utf-8");
	}

	public static String postWs(String url, String data, String encode) throws Exception {
		HttpClient httpclient = new HttpClient();
		PostMethod postMethod = new PostMethod(url);
		if (StringUtils.isBlank(encode)) {
			encode = "utf-8";
		}
		postMethod.setRequestEntity(new StringRequestEntity(data.toString(), "text/xml", encode));
		httpclient.executeMethod(postMethod);
		String response = postMethod.getResponseBodyAsString();
		return response;
	}
	
}
